/**
 * Created on : 2015/11/28
 * Author     : @kankan
 */

// create xupload object
var xupload = xupload || {};

(function() {
	
    /**************************************************
     * XUpload
     **************************************************/
    var XUpload = function(obj, options) {
		var self = this;
    	
		self.$obj = obj;								// 加了$只是为了区分Js变量而已，可以用来表示这个变量是一个jquery对象，没其他含义
		self.$options = options;

		self._init();
    };
    
    XUpload.prototype = {
        /* 初始化 */
        _init: function() {
            var self = this;
            
            self._preProcess();
            self._onChange     = self._onChange.bind(self);
		    self._clearElement = self._clearElement.bind(self);
		
		    self._translate();
            self._createDomElem();
		    self._setSize();
       //     self._show();
            
            $(self.$obj).on('change', self._onChange);
    		
            return self;								// VERY IMPORTANT!!! 这样才能继续调用后面的其它方法
        },
        
        /* 预处理 */
        _preProcess: function() {
            var self = this;
            
            self.$options = $.extend({}, XUpload.DEFAULTS, self.$options);		// 将调用者的参数与本对象的默认参数进行合并
        },
    	
    	/* Translate text if needed */
    	_translate: function() {
    	    for (var name in this.$options.tpl) {
    	        for (var key in this.$options.messages) {
    	            this.$options.tpl[name] = this.$options.tpl[name].replace('{{ ' + key + ' }}', this.$options.messages[key]);
    	        }
    	    }
    	},
    	
    	/* Create dom elements */
    	_createDomElem: function() {
    	    $(this.$obj).wrap($(this.$options.tpl.wrap));
    	    this.wrapper = $(this.$obj).parent();
    	
    	    var messageWrapper = $(this.$options.tpl.message).insertBefore($(this.$obj));
    	    $(this.$options.tpl.error).appendTo(messageWrapper);
    	
    	    if (this.$options.isDisabled) {
    	    	$(this.$obj).attr('disabled', 'disabled');
    	        this.isDisabled = true;
    	        this.wrapper.addClass('disabled');
    	    }
    	
    	    this.preview = $(this.$options.tpl.preview);
    	    this.preview.insertAfter($(this.$obj));
    	
    	    if (this.$options.isDisabled === false && this.$options.disableRemove !== true) {
    	        this.clearButton = $(this.$options.tpl.clearButton);
    	        this.clearButton.insertAfter($(this.$obj));
    	        this.clearButton.on('click', this._clearElement);
    	    }
    	
    	    this.filenameWrapper = $(this.$options.tpl.filename);
    	    this.filenameWrapper.prependTo(this.preview.find('.xupload-infos-inner'));
    	
    	    this._setFile(this.$options.defaultFile);
    	},

    	/* Set the filename in the object and in the dom */
    	_setFilename: function(filename) {
    	    var filename = this._getFilename(filename);
    	    this.filename = filename;
    	    this.filenameWrapper.children('.xupload-filename-inner').html(filename);
    	},

    	/* Set the preview and animate it */
    	_setPreview: function(src) {
    	    this.wrapper.removeClass('has-error').addClass('has-preview');
    	    var render = this.preview.children('.xupload-render');
    	    
    	    if (this._isImage() === true) {
    	        $('<img />').attr('src', src).appendTo(render);
    	    } else {
    	        $('<i />').attr('class', 'xupload-font-file').appendTo(render);
    	        $('<span class="xupload-extension" />').html(this._getFileType()).appendTo(render);
    	    }
    	
    	    this.preview.fadeIn();
    	},

    	/* Get the filename */
    	_getFilename: function(src) {
    	    var filename = src.split('\\').pop();
    	    if (filename == src) {
    	        filename = src.split('/').pop();
    	    }
    	
    	    return src != "" ? filename : '';
    	},
    	
    	/* Get the file type */
    	_getFileType: function() {
    	    return this.filename.split('.').pop().toLowerCase();
    	},
    	
    	/* Test if the file is an image */
    	_isImage: function() {
    	    if (this.$options.imgFileFormats.indexOf(this._getFileType()) != "-1") {
    	        return true;
    	    }
    	
    	    return false;
    	},
    	
    	/* Check the limit filesize */
    	_checkFileSize: function() {
    	    if (this._maxFileSizeToByte() === 0 || this.file.size <= this._maxFileSizeToByte()) {
    	        return true;
    	    }
    	
    	    return false;
    	},
    	
    	/* Convert filesize to byte */
    	_maxFileSizeToByte: function() {
    	    var value = 0;
    	
    	    if (this.$options.maxFileSize !== 0) {
    	        var unit  = this.$options.maxFileSize.slice(-1).toUpperCase(),
    	            kb    = 1024,
    	            mb    = kb * 1024,
    	            gb    = mb * 1024;
    	
    	        if (unit === 'K') {
    	            value = parseFloat(this.$options.maxFileSize) * kb;
    	        } else if (unit === 'M') {
    	            value = parseFloat(this.$options.maxFileSize) * mb;
    	        } else if (unit === 'G') {
    	            value = parseFloat(this.$options.maxFileSize) * gb;
    	        }
    	    }
    	
    	    return value;
    	},

    	/* Set the wrapper height */
    	_setSize: function() {
    	    if (this.$options.height) {
    	        this.wrapper.height(this.$options.height);
    	    }
    	},
        
        /* On change event */
        _onChange: function() {
    	    this._resetPreview();
    	    this._setFilename($(this.$obj).val());
    	    this._readUrl($(this.$obj)[0]);					// $(this.$obj)[0] == input
    	    
    	    if (this.$options.changeHandler && typeof this.$options.changeHandler === 'function') {				// 清空或更改时用户回调
    	    	this.$options.changeHandler(this);
            }
    	},

    	/* Reset the preview */
    	_resetPreview: function(){
    	    this.wrapper.removeClass('has-preview');
    	    var render = this.preview.children('.xupload-render');
    	    render.find('.xupload-extension').remove();
    	    render.find('i').remove();
    	    render.find('img').remove();
    	    this.preview.hide();
    	},

    	/* Read the file url using FileReader */
    	_readUrl: function(input) {
    	    if (input.files && input.files[0]) {
    	        var reader = new FileReader();
    	        this.file = input.files[0];
    	
    	        if (this._checkFileSize()) {
    	            reader.onload = function(e) {
    	                this._setPreview(e.target.result);
    	            }.bind(this);
    	
    	            reader.readAsDataURL(this.file);
    	        } else {
    	            this.wrapper.addClass('has-error');
    	            this._resetPreview();
    	            this._clearElement();
    	        }
    	    }
    	},

    	/* Clear the element, events are available */
    	_clearElement: function() {
    	    var eventBefore = $.Event("xupload.beforeClear");
    	    $(this.$obj).trigger(eventBefore, [this]);
    	
    	    if (eventBefore.result !== false) {
    	        this.file = null;
    	        $(this.$obj).val('');
    	        this._resetPreview();
    	
    	        var eventAfter = $.Event("xupload.afterClear");
    	        $(this.$obj).trigger(eventAfter, [this]);
    	    }
    	    
    	    if (this.$options.changeHandler && typeof this.$options.changeHandler === 'function') {				// 用户回调
    	    	this.$options.changeHandler(this);
            }
    	},
    	
    	/* Set the file's text and preview */
    	_setFile: function(filename) {
    		filename = filename || '';
    	    if (filename.trim() != '') {
    	        this._setFilename(filename);
    	        this._setPreview(filename);
    	    }
    	    
    	    //return this;
    	},

        /******************* 公共方法 *******************/
    	/* Set the file's text and preview */
    	setFile: function(src) {
    		src = src || '';
    	    if (src.trim() != '') {
    	    	this._resetPreview();
    	        this._setPreview(src);
    	    }
    	    
    	    //return this;
    	}
	};

    XUpload.DEFAULTS = {
        defaultFile: '',
        maxFileSize: 0,
        messages: {
            'default': 'Drag and drop a file here or click',
            'replace': 'Drag and drop or click to replace',
            'error':   'Sorry, this file is too large'
        },
        tpl: {
            wrap:        '<div class="xupload-wrapper"></div>',
            message:     '<div class="xupload-message"><span class="file-icon" /> <p>{{ default }}</p></div>',
            preview:     '<div class="xupload-preview"><span class="xupload-render"></span><div class="xupload-infos"><div class="xupload-infos-inner"><p class="xupload-infos-message">{{ replace }}</p></div></div></div>',
            filename:    '<p class="xupload-filename"><span class="file-icon"></span><span class="xupload-filename-inner"></span></p>',
            clearButton: '<button type="button" class="xupload-clear" title="批量删除"><i class="fa fa-trash"></i></button>',
            error:       '<p class="xupload-error">{{ error }}</p>'
        },
        wrapper         : null,
        preview         : null,
        filenameWrapper : null,
        imgFileFormats  : ['png', 'jpg', 'jpeg', 'gif', 'bmp'],
        file            : null,
        filename        : null,
        isDisabled      : false,
        height			: 200,
        changeHandler	: null,
    };
    
    /* xupload */
	xupload = function(obj, options) {
		return new XUpload(obj, options);
    };
    xupload.defaults = XUpload.DEFAULTS;
    
})();